package com.service.single.example.sftp;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Properties;

/**
 * 利用sftp上传文件信息(账号密码 / ssh 私钥 连接)
 * 问题发现：该版本 JSch 不支持OpenSSH_8.6p1 向  OpenSSH_7.4p1 发起连接
 * 报错 com.jcraft.jsch.JSchException: invalid privatekey: [B@172bd4cc
 */
@Slf4j
public class SFTPService {

    @Value("${csv.host}")
    private String host;
    @Value("${csv.port:22}")
    private Integer port;
    @Value("${csv.username}")
    private String username;
    @Value("${csv.password}")
    private String password;
    /**
     * ssh 私钥全路径
     */
    @Value("${csv.idRsaPath}")
    private String idRsaPath;
    /**
     * 需要上传到服务器的路径
     */
    @Value("${csv.sftpPath}")
    private String sftpPath;


    /**
     * sftp 连接
     */
    private ChannelSftp getChannel() {
        try {
            // 创建JSch对象
            JSch jSch = new JSch();
            // 根据用户名，主机ip，端口获取一个Session对象
            Session session = jSch.getSession(username, host, port);
            // 密码方式连接
            session.setPassword(password);
            // 密钥方式连接
            // jSch.addIdentity(idRsaPath);
            Properties properties = new Properties();
            //主机公钥确认 无口令 SSH 登录（即通过客户端公钥认证），就可以直接连接到远程主机。
            //这是基于 SSH 协议的自动化任务常用的手段
            properties.put("StrictHostKeyChecking", "no");
            // 为Session对象设置properties
            session.setConfig(properties);
            // 设置timeout时间
            session.setTimeout(60000);
            // 通过Session建立链接
            session.connect();
            // 打开SFTP通道
            Channel channel = session.openChannel("sftp");
            // 建立SFTP通道的连接
            channel.connect();
            return (ChannelSftp) channel;
        } catch (Exception e) {
            log.error("创建sftp连接失败 {}", e);
        }
        return null;
    }

    /**
     * 利用sftp上传文件
     *
     * @param filePath 文件全路径,例：/opt/data/xxx.txt
     */
    public void push(String filePath) {
        ChannelSftp channelSftp = this.getChannel();
        try {
            if (ObjectUtils.isNotEmpty(channelSftp)) {
                channelSftp.put(filePath, sftpPath);
                channelSftp.disconnect();
                log.info("文件上传成功 {}", LocalDateTime.now());
            }
        } catch (Exception e) {
            log.info("文件上传失败");
        }
    }
}
